A Web server is primarily a server application that
can be contacted using a bunch of Internet protocols, such as HTTP, File
Transfer Protocol (FTP), Network News Transfer Protocol (NNTP), and the
Simple Mail Transfer Protocol (SMTP). IIS—the Web server included with
the Microsoft Windows operating system—is no exception.
A Web server
generally also provides a documented application programming interface
(API) for enhancing and customizing the server’s capabilities.
Historically speaking, the first of these extension APIs was the Common
Gateway Interface (CGI). A CGI module is a new application that is
spawned from the Web server to service a request. Nowadays, CGI
applications are almost never used in modern Web applications because
they require a new process for each HTTP request. As you can easily
understand, this approach is rather inadequate for high-volume Web sites
and poses severe scalability issues. IIS supports CGI applications, but
you will seldom use this feature unless you have serious
backward-compatibility issues. More recent versions of Web servers
supply an alternate and more efficient model to extend the capabilities
of the module. In IIS, this alternative model takes the form of the
ISAPI interface.
The ISAPI Model
When the ISAPI model is
used, instead of starting a new process for each request, IIS loads an
ISAPI component—namely, a Win32 DLL—into its own process. Next, it calls
a well-known entry point on the DLL to serve the request. The ISAPI
component stays loaded until IIS is shut down and can service requests
without any further impact on Web server activity. The downside
to such a model is that because components are loaded within the Web
server process, a single faulty component can tear down the whole server
and all installed applications. Starting with IIS 4.0, though, some
countermeasures have been taken to address this problem. Before the
advent of IIS 6.0, you were allowed to set the protection level of a
newly installed application choosing from three options: low, medium,
and high.
If you choose a low protection, the application (and its extensions) will be run within the Web server process (inetinfo.exe).
If you choose medium protection, applications will be pooled together
and hosted by an instance of a different worker process (dllhost.exe). If you choose high protection, each application set to High will be hosted in its own individual worker process (dllhost.exe).
Web applications running
under IIS 6.0 are grouped in pools, and the choice you can make is
whether you want to join an existing pool or create a new one. Figure 1 shows the dialog box picking the application pool of choice in IIS 6.0 and Microsoft Windows Server 2003.
All applications in a pool share the same run-time settings and the same worker process—w3wp.exe.
Illustrious Children of the ISAPI Model
The ISAPI model has
another key drawback—the programming model. An ISAPI component
represents a compiled piece of code—a Win32 DLL—that retrieves data and
writes HTML code to an output console. It has to be developed using C or
C++, it should generate multithreaded code, and it must be written with
extreme care because of the impact that bugs or runtime failures can
have on the application.
A
while back, Microsoft attempted to encapsulate the ISAPI logic in the
Microsoft Foundation Classes (MFC), but even though the effort was
creditable, it didn’t pay off very well. MFC tended to bring more code
to the table than high-performance Web sites would perhaps like, and
worse, the resulting ISAPI extension DLL suffered from a well-documented
memory leak.
Active Server
Pages (ASP), the predecessor of ASP.NET, is, on the other hand, an
example of a well-done ISAPI application. ASP is implemented as an ISAPI
DLL (named asp.dll) registered to handle HTTP requests with an .asp
extension. The internal code of the ASP ISAPI extension DLL parses the
code of the requested resource, executes any embedded script code, and
builds the page for the browser.
As of IIS 6.0, any
functionality built on top of IIS must be coded according to the
guidelines set by the ISAPI model. ASP and ASP.NET are no exceptions.
Today, the whole ASP.NET platform works closely with IIS, but it is not
part of it. The aspnet_isapi.dll core component is the link between IIS and the ASP.NET runtime environment. When a request for .aspx resources comes in, IIS passes the control to aspnet_isapi.dll, which in turn hands the request to the ASP.NET pipeline inside an instance of the common language runtime (CLR).
As of this writing, to
extend IIS you can write a Win32 DLL only with a well-known set of entry
points. This requirement ceases to exist with IIS 7.0, which is
scheduled to ship with Windows 2008 Server.
Structure of ISAPI Components
An ISAPI
extension is invoked through a URL that ends with the name of the DLL
that implements the function, as shown in the following URL:
http://www.contoso.com/apps/hello.dll
The DLL must export a couple of functions—GetExtensionVersion and HttpExtensionProc. The GetExtensionVersion function sets the version and the name of the ISAPI server extension. When the extension is loaded, the GetExtensionVersion function is the first function to be called. GetExtensionVersion is invoked only once and can be used to initialize any needed variables. The function is expected to return true if everything goes fine. In the case of errors, the function should return false and the Web server will abort loading the DLL and put a message in the system log.
The core of the ISAPI component is represented by the HttpExtensionProc
function. The function receives basic HTTP information regarding the
request (for example, the query string and the headers), performs the
expected action, and prepares the response to send back to the browser.
Note
Certain
handy programming facilities, such as the session state, are
abstractions the ISAPI programming model lacks entirely. The ISAPI model
is a lower level programming model than, say, ASP or ASP.NET. |
The ISAPI programming model is made of two types of components—ISAPI extensions and ISAPI filters.
ISAPI Extensions
ISAPI extensions are the
IIS in-process counterpart of CGI applications. As mentioned, an ISAPI
extension is a DLL that is loaded in the memory space occupied by IIS or
another host application. Because it is a DLL, only one instance of the
ISAPI extension needs to be loaded at a time. On the downside, the
ISAPI extension must be thread-safe so that multiple client requests can
be served simultaneously. ISAPI extensions work in much the same way as
an ASP or ASP.NET page. It takes any information about the HTTP request
and prepares a valid HTTP response.
Because the ISAPI
extension is made of compiled code, it must be recompiled and reloaded
at any change. If the DLL is loaded in the Web server’s memory, the Web
server must be stopped. If the DLL is loaded in the context of a
separate process, only that process must be stopped. Of course, when an
external process is used, the extension doesn’t work as fast as it could
when hosted in-process, but at least it doesn’t jeopardize the
stability of IIS.
ISAPI Filters
ISAPI filters are
components that intercept specific server events before the server
itself handles them. Upon loading, the filter indicates what event
notifications it will handle. If any of these events occur, the filter
can process them or pass them on to other filters.
You can use ISAPI
filters to provide custom authentication techniques or to automatically
redirect requests based on HTTP headers sent by the client. Filters are a
delicate gear in the IIS machinery. They can facilitate applications
and let them take control of customizable aspects of the engine. For
this same reason, though, ISAPI filters can also degrade performance if
not written carefully. Filters, in fact, can run only in-process.
Filters can be loaded for the Web server as a whole or for specific Web
sites.
ISAPI filters can
accomplish tasks such as implementing custom authentication schemes,
compression, encryption, logging, and request analysis. The ability to
examine, and if necessary modify, both incoming and outgoing streams of
data makes ISAPI filters very powerful
and flexible. This last sentence shows the strength of ISAPI filters
but also indicates their potential weakness, which is that they will
hinder performance if not written well.
Changes in IIS 7.0
ASP.NET 1.0 was
originally a self-contained, brand new runtime environment bolted onto
IIS 5.0. With the simultaneous release of ASP.NET 1.1 and IIS 6.0, the
Web development and server platforms have gotten closer and started
sharing some services, such as process recycling and output caching. The
advent of ASP.NET 2.0 and newer versions hasn’t changed anything, but
the release of IIS 7.0 will.
A Unified Runtime Environment
In a certain way, IIS 7.0
represents the unification of the ASP.NET and IIS platforms. HTTP
handlers and modules, the runtime pipeline, and configuration files will
become constituent elements of a common environment. The whole IIS
internal pipeline has been componentized to originate a distinct and
individually configurable component. A new section will be added to the web.config schema of ASP.NET applications to configure the IIS environment.
Put another way, it will be
as if the ASP.NET runtime expanded to incorporate and replace the
surrounding Web server environment. It’s hard to say whether things
really went this way or whether it was the other way around. As a matter
of fact, the same concepts and instruments you know from ASP.NET are
available in IIS 7.0 at the Web server level.
To illustrate, on
Windows 2008 Server (and for testing purposes, also on a Windows Vista
machine) you can use Forms authentication to protect access to any
resources available on the server and not just ASP.NET-specific
resources. You might already know that static resources such as HTML
pages and JPG images are not served by ASP.NET by default; as such,
they’re not subject to the authentication rules you set for the
application. Where IIS 7.0 is supported, you can now define a handler
for some specific and static resources and be sure that IIS will use
your code to serve those resources.
Managed ISAPI Extensions and Filters
Today if you want to
take control of an incoming request in any version of IIS older than
version 7.0, you have no choice other than writing a C or C++ DLL, using
either MFC or perhaps the ActiveX Template Library (ATL). More
comfortable HTTP handlers and modules are an ASP.NET-only feature, and
they can be applied only to ASP.NET-specific resources and only after
the request has been authenticated by IIS and handed over to ASP.NET.
In IIS 7.0, you can write HTTP handlers and modules to filter any
requests and implement any additional features using .NET code for
whatever resources the Web server can serve. More precisely, you’ll
continue writing HTTP handlers and modules as you do today for ASP.NET, except
that you will be given the opportunity to register them for any file
type. Needless to say, old-style ISAPI extensions will still be
supported, but unmanaged extensions and filters will likely become a
thing of the past.